package com.lwm.service.impl;

import cn.hutool.jwt.JWTPayload;
import com.lwm.domain.LoginUser;
import com.lwm.domain.ResponseResult;
import com.lwm.domain.User;
import com.lwm.mapper.UserMapper;
import com.lwm.service.LoginService;
import com.lwm.utils.JWTUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private RedisTemplate<Object, Object> redisTemplate;
    @Resource
    private UserMapper userMapper;

    /**
     * 登录
     *
     * @param user 用户
     * @return {@link ResponseResult}<{@link Object}>
     */
    @Override
    public ResponseResult<Object> login(User user) {
        // 1.进行用户认证 AuthenticationManager authenticate
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        // Authentication 封装着用户信息
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

        // 2.认证失败
        if (Objects.isNull(authenticate)) throw new RuntimeException("用户名或密码错误");

        // 3.认证通过，使用userId生成jwt
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        // 载荷
        HashMap<String, Object> payload = new HashMap<>();
        payload.put("id", userId);
        String token = JWTUtils.createToken(payload);
        // data格式：{"token":"jwt"}
        HashMap<String, String> map = new HashMap<>();
        map.put("token", token);

        // 4.将完整的信息存入Redis，userId为key
        redisTemplate.opsForValue().set("login:" + userId, loginUser);

        return new ResponseResult<>(200, "登录成功", map);
    }

    /**
     * 注销
     *
     * @return {@link ResponseResult}<{@link Object}>
     */
    @Override
    public ResponseResult<Object> logout() {
        // 1.在SecurityContextHolder中，获取用户id
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        Long userId = loginUser.getUser().getId();
        // 2.移除对应在Redis中的数据
        redisTemplate.delete("login:" + userId);
        return new ResponseResult<>(200,"退出登录成功");
    }

    /**
     * 获取用户信息
     *
     * @param token 令牌
     * @return {@link ResponseResult}<{@link Object}>
     */
    @Override
    public ResponseResult<Object> getInfo(String token) {
        Map<String,Object> map = new HashMap<>();
        try {
            // 解析token，获取用户id
            JWTPayload jwtPayload = JWTUtils.parseToken(token);
            Long id = Long.parseLong(jwtPayload.getClaim("id").toString());
            // 根据用户id查询用户信息
            User user = userMapper.selectById(id);
            Integer userType = user.getUserType();
            map.put("name",user.getUsername());
            map.put("email",user.getEmail());
            // 处理用户类型
            if (userType == 0) map.put("roles", Collections.singletonList("admin"));
            if (userType == 1) map.put("roles", Collections.singletonList("other"));
            map.put("avatar",user.getAvatar());
            map.put("introduction",user.getIntroduction());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("token 非法");
        }
        return new ResponseResult<>(200,"请求成功",map);
    }
}
